/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * The software in this package is published under the terms of the GPL v2.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE-GPL.txt file.
 */

package org.cemantika.infrastructure.dao;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.cemantika.infrastructure.model.PersistentEntity;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

/**
 * BaseDao represents the implementation of generic data persistence layer. Simplifies Hibernate
 * data access code, and all exceptions follow the org.springframework.dao exception hierarchy.
 * 
 * @author andersonfellipe
 */
@SuppressWarnings("restriction")
public abstract class BaseDao<Entity extends PersistentEntity> extends HibernateDaoSupport implements IBaseDao<Entity> {

    /**
     * Represents the class of entity persistent
     */
    private final transient Class<Entity> entityClass;

    /**
     * Creates a new instance of the persistence layer with the default values.
     */
    @SuppressWarnings("unchecked")
    public BaseDao() {
        super();
        this.entityClass =
                (Class<Entity>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    /* (non-Javadoc)
     * @see org.cemantika.infrastructure.dao.IBaseDao#save(org.cemantika.infrastructure.model.PersistentEntity)
     */
    public Entity save(final Entity obj) {
        super.getHibernateTemplate().save(obj);
        this.getHibernateTemplate().flush();
        return obj;
    }

    /* (non-Javadoc)
     * @see org.cemantika.infrastructure.dao.IBaseDao#update(org.cemantika.infrastructure.model.PersistentEntity)
     */
    public Entity update(final Entity obj) {
        super.getHibernateTemplate().merge(obj);
        this.getHibernateTemplate().flush();
        return obj;
    }

    /* (non-Javadoc)
     * @see org.cemantika.infrastructure.dao.IBaseDao#delete(org.cemantika.infrastructure.model.PersistentEntity)
     */
    public void delete(final Entity obj) {
        super.getHibernateTemplate().delete(super.getHibernateTemplate().merge(obj));
    }

    /* (non-Javadoc)
     * @see org.cemantika.infrastructure.dao.IBaseDao#find(java.lang.String)
     */
    @SuppressWarnings("unchecked")
    public List<Entity> find(final String queryString) {
        return super.getHibernateTemplate().find(queryString);
    }

    /* (non-Javadoc)
     * @see org.cemantika.infrastructure.dao.IBaseDao#findAll()
     */
    @SuppressWarnings("unchecked")
    public List<Entity> findAll() {
        return super.getHibernateTemplate().loadAll(this.entityClass);
    }

    /* (non-Javadoc)
     * @see org.cemantika.infrastructure.dao.IBaseDao#findById(java.lang.Object)
     */
    @SuppressWarnings("unchecked")
    public Entity findById(final Object identifier) {
        Entity result = null;
        List<Entity> list;

        final Criteria crit = getSession().createCriteria(this.entityClass); 
        crit.add(Restrictions.eq("id", identifier));
        list = crit.list();

        if (list != null && !list.isEmpty()) {
            result = list.get(0);
        }

        return result;
    }
    
}
